package game.main;

import game.componentes.Matriz;
import game.componentes.Matriz.Marcou;
import game.util.Computador;
import game.util.Jogador;
import game.util.Marc;
import game.util.Modalidade;
import game.util.Verificacao;
import game.util.Vitoria;
import android.app.Activity;
import static android.graphics.Color.BLUE;
import static android.graphics.Color.RED;
import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
import android.widget.Toast;

public class GameActivity extends Activity implements OnTouchListener {
	private int vp1 = 0, vp2 = 0, empates = 0;
	private static final Marc[][] jogo = new Marc[3][3];
	private static int jogadas = 0;
	private Computador computador;
	private Jogador iniciante = Jogador.PLAYER1;
	private Modalidade modalidade = MainActivity.getModalidade();
	private Jogador jogadorAtual = iniciante;
	private static Vitoria vitoria;
	private boolean empatou = false;
	private boolean limpou = false;
	public static String player1 = "Humano";
	public static String player2 = "Computador";

	private TextView tvRemoto;
	private TextView tvEmpates;
	private TextView tvPlayer1;
	private TextView tvPlayer2;
	private TextView tvVitoriasP1;
	private TextView tvVitoriasP2;

	private String dispositivoRemoto;

	public void setDispositivoRemoto(String dispositivoCliente) {
		this.dispositivoRemoto = dispositivoCliente;
	}

	public static Marc[][] getJogo() {
		return jogo.clone();
	}

	public static Vitoria getVitoria() {
		return vitoria;
	}

	public static int getJogadas() {
		return jogadas;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_game);
		Matriz matriz = (Matriz) findViewById(R.id.matriz);
		matriz.setMarcou(marcou);
		jogadorAtual = iniciante;
		if (Modalidade.ONEPLAYER.equals(modalidade)) {
			computador = new Computador(marcou);
			player1 = "Humano";
			player2 = "Computador";
		}
		matriz.setOnTouchListener(this);

		tvRemoto = (TextView) findViewById(R.id.dispositivo_remoto);
		tvVitoriasP1 = (TextView) findViewById(R.id.vitoriasP1);
		tvVitoriasP2 = (TextView) findViewById(R.id.vitoriasP2);
		tvPlayer1 = (TextView) findViewById(R.id.tvPlayer1);
		tvPlayer2 = (TextView) findViewById(R.id.tvPlayer2);
		tvEmpates = (TextView) findViewById(R.id.empates);

		limpar();
		limpou = false;
	}

	@Override
	protected void onResume() {
		super.onResume();
		tvRemoto.setText(dispositivoRemoto);
	}

	public Marcou getMarcou() {
		return marcou;
	}

	private Marcou marcou = new Marcou() {
		@Override
		public void onMark(Point p) {
			if (limpou) {
				limpou = false;
				return;
			}
			Log.i("tic-tac", String.format("%s, Jogada: %d, Player: %s", p.toString(), jogadas, jogadorAtual.name()));
			if (jogo[p.x][p.y] == null && (vitoria == null) && !empatou) {
				jogo[p.x][p.y] = getMarc();

				if (!verificarFim()) {
					jogadas++;
					alternarJogadores();
					playComputer();
					definirJogadaDaVez();
				}
			}
		}
	};

	private void playComputer() {
		if (Modalidade.ONEPLAYER.equals(modalidade) && jogadorAtual.equals(Jogador.COMPUTER))
			computador.realizarMarcacao(getJogo(), getMarc());
	}

	private void alternarJogadores() {
		if (Modalidade.ONEPLAYER.equals(modalidade)) {
			if (Jogador.PLAYER1.equals(jogadorAtual)) {
				jogadorAtual = Jogador.COMPUTER;
			} else {
				jogadorAtual = Jogador.PLAYER1;
			}
		} else {
			if (Jogador.PLAYER1.equals(jogadorAtual)) {
				jogadorAtual = Jogador.PLAYER2;
			} else {
				jogadorAtual = Jogador.PLAYER1;
			}
		}
	}

	private void definirJogadaDaVez() {
		if (jogadorAtual.equals(Jogador.PLAYER1)) {
			tvPlayer1.setText("> " + player1 + ":");
			tvPlayer2.setText(player2 + ":");
		} else {
			tvPlayer1.setText(player1 + ":");
			tvPlayer2.setText("> " + player2 + ":");
		}
	}

	/**
	 * Verifica o fim do jogo.
	 * @return <code>true</code> caso o jogo chegou ao fim.
	 */
	private boolean verificarFim() {
		Vitoria vitoria = Verificacao.verificar(jogo, getMarc());
		if (vitoria != null) {
			Toast.makeText(this, String.format("%S ganhou!", getMarc().name()), Toast.LENGTH_LONG).show();
			Log.i("tic-tac", String.format("Player: %s (%s) ganhou...", jogadorAtual.name(), getMarc().name()));
			Log.i("tic-tac", String.format("Vitoria: %s ", vitoria.name()));
			iniciante = jogadorAtual;

			if (jogadorAtual.equals(Jogador.PLAYER1))
				vp1++;
			else
				vp2++;

			GameActivity.vitoria = vitoria;
			return true;
		} else if (jogadas == 8) {
			Toast.makeText(this, "Deu velha!", Toast.LENGTH_LONG).show();
			Log.i("tic-tac", "DEU VELHA!!!");
			alternarJogadores();
			iniciante = jogadorAtual;
			empatou = true;
			empates++;
			return true;
		}
		return false;
	}

	private void limpar() {
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				jogo[i][j] = null;
		jogadas = 0;
		empatou = false;
		vitoria = null;
		limpou = true;
		
		if (iniciante.equals(Jogador.PLAYER1)) {
			setColor(tvPlayer1, BLUE);
			setColor(tvVitoriasP1, BLUE);
			setColor(tvPlayer2, RED);
			setColor(tvVitoriasP2, RED);
		} else {
			setColor(tvPlayer1, RED);
			setColor(tvVitoriasP1, RED);
			setColor(tvPlayer2, BLUE);
			setColor(tvVitoriasP2, BLUE);
		}
		
		definirJogadaDaVez();

		tvVitoriasP2.setText(String.valueOf(vp2));
		tvVitoriasP1.setText(String.valueOf(vp1));
		tvEmpates.setText(String.valueOf(empates));

		Log.i("tic-tac", String.format("Novo jogo. Iniciante: %s ", iniciante));
		playComputer();
	}
	
	private void setColor(TextView textView, int color) {
		textView.setTextColor(color);
	}

	private Marc getMarc() {
		if (jogadorAtual.equals(iniciante))
			return Marc.X;
		else
			return Marc.O;
	}

	@Override
	public boolean onTouch(View view, MotionEvent event) {
		if (vitoria != null || empatou) {
			limpar();
		}
		return false;
	}
}
